/*
 * libPaquetes.c
 *
 *  Created on: 22/04/2012
 *      Author: utnso
 */

#include "libPaquetes.h"

char* serializar(paquete_t paquete){
	char* buffer = malloc(paquete.pLength + 3);
	buffer[0] = paquete.tipo;
	memcpy(buffer + 1, &(paquete.pLength), 2);
	if(paquete.pLength > 0){
		memcpy(buffer + 3, paquete.payload, paquete.pLength);
	}
	return buffer;
}

paquete_t deserializar(char* buffer){
	paquete_t paquete;
	paquete.tipo = buffer[0];
	memcpy(&(paquete.pLength), buffer + 1, 2);
	if(paquete.pLength > 0){
		paquete.payload = (char*) malloc(paquete.pLength);
		memcpy(paquete.payload, buffer + 3, paquete.pLength);
	}else{
		paquete.payload = NULL;
	}
	return paquete;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioCrearArchivo(argCrearArch_t arg){
	return sizeof(uint64_t) + strlen(arg.path) + sizeof(mode_t);
}

argCrearArch_t parsearEnvioCrearArchivo(char* payload){
	//[LONG_PATH][PATH][MODO]
	argCrearArch_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;
	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL MODO
	memcpy(&(arg.modo), payload + desplazamiento, sizeof(mode_t));

	return arg;
}

char* desparsearEnvioCrearArchivo(argCrearArch_t arg){
	//[LONG_PATH][PATH][MODO]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioCrearArchivo(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path), &(arg.modo), sizeof(mode_t));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioAbrirArchivo(argAbrirArch_t arg){
	return sizeof(uint64_t) + strlen(arg.path);
}

argAbrirArch_t parsearEnvioAbrirArchivo(char* payload){
	//[LONG_PATH][PATH]
	argAbrirArch_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';

	return arg;
}

char* desparsearEnvioAbrirArchivo(argAbrirArch_t arg){
	//[LONG_PATH][PATH]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioAbrirArchivo(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioLeerArchivo(argLeerArch_t arg){
	return sizeof(uint64_t) + strlen(arg.path) + sizeof(size_t) + sizeof(off_t);
}

argLeerArch_t parsearEnvioLeerArchivo(char* payload){
	//[LONG_PATH][PATH][SIZE][OFFSET]
	argLeerArch_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL TAMANIO
	memcpy(&(arg.size), payload + desplazamiento, sizeof(size_t));
	desplazamiento += sizeof(size_t);

	//PARSEAMOS EL OFFSET
	memcpy(&(arg.offset), payload + desplazamiento, sizeof(off_t));

	return arg;
}

char* desparsearEnvioLeerArchivo(argLeerArch_t arg){
	//[LONG_PATH][PATH][SIZE][OFFSET]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioLeerArchivo(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path), &(arg.size), sizeof(size_t));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path) + sizeof(size_t), &(arg.offset), sizeof(off_t));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioEscribirArchivo(argEscribirArch_t arg){
	return sizeof(uint64_t) + strlen(arg.path) + sizeof(size_t) + arg.size + sizeof(off_t);
}

argEscribirArch_t parsearEnvioEscribirArchivo(char* payload){
	//[LONG_PATH][PATH][SIZE][BUFFER][OFFSET]
	argEscribirArch_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL TAMANIO
	memcpy(&(arg.size), payload + desplazamiento, sizeof(size_t));
	desplazamiento += sizeof(size_t);

	//PARSEAMOS EL BUFFER
	arg.buffer = (char*) malloc(arg.size);
	memcpy(arg.buffer, payload + desplazamiento, arg.size);

	//PARSEAMOS EL OFFSET
	memcpy(&(arg.offset), payload + desplazamiento, sizeof(off_t));

	return arg;
}

char* desparsearEnvioEscribirArchivo(argEscribirArch_t arg){
	//[LONG_PATH][PATH][SIZE][BUFFER][OFFSET]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioEscribirArchivo(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path), &(arg.size), sizeof(size_t));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path) + sizeof(size_t), arg.buffer, arg.size);
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path) + sizeof(size_t) + arg.size, &(arg.offset), sizeof(off_t));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioBorrarArchivo(argBorrarArch_t arg){
	return sizeof(uint64_t) + strlen(arg.path);
}

argBorrarArch_t parsearEnvioBorrarArchivo(char* payload){
	//[LONG_PATH][PATH]

	argBorrarArch_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';

	return arg;
}

char* desparsearEnvioBorrarArchivo(argBorrarArch_t arg){
	//[LONG_PATH][PATH]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioBorrarArchivo(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioTruncarArchivo(argTruncarArch_t arg){
	return sizeof(uint64_t) + strlen(arg.path) + sizeof(off_t);
}

argTruncarArch_t parsearEnvioTruncarArchivo(char* payload){
	//[LONG_PATH][PATH][OFFSET]

	argTruncarArch_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;
	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL OFFSET
	memcpy(&(arg.offset), payload + desplazamiento, sizeof(off_t));

	return arg;
}

char* desparsearEnvioTruncarArchivo(argTruncarArch_t arg){
	//[LONG_PATH][PATH][OFFSET]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioTruncarArchivo(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path), &(arg.offset), sizeof(off_t));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioCerrarArchivo(argCerrarArch_t arg){
	return sizeof(uint64_t) + strlen(arg.path);
}

argCerrarArch_t parsearEnvioCerrarArchivo(char* payload){
	//[LONG_PATH][PATH]

	argCerrarArch_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';

	return arg;
}

char* desparsearEnvioCerrarArchivo(argCerrarArch_t arg){
	//[LONG_PATH][PATH]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioCerrarArchivo(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioCrearDirectorio(argCrearDir_t arg){
	return sizeof(uint64_t) + strlen(arg.path) + sizeof(mode_t);
}

argCrearDir_t parsearEnvioCrearDirectorio(char* payload){
	//[LONG_PATH][PATH][MODO]
	argCrearDir_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;
	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL MODO
	memcpy(&(arg.modo), payload + desplazamiento, sizeof(mode_t));

	return arg;
}

char* desparsearEnvioCrearDirectorio(argCrearDir_t arg){
	//[LONG_PATH][PATH][MODO]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioCrearDirectorio(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path), &(arg.modo), sizeof(mode_t));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioLeerDirectorio(argLeerDir_t arg){
	return sizeof(uint64_t) + strlen(arg.path) + sizeof(off_t);
}

argLeerDir_t parsearEnvioLeerDirectorio(char* payload){
	//[LONG_PATH][PATH][OFFSET]

	argLeerDir_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;
	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL OFFSET
	memcpy(&(arg.offset), payload + desplazamiento, sizeof(off_t));

	return arg;
}

char* desparsearEnvioLeerDirectorio(argLeerDir_t arg){
	//[LONG_PATH][PATH][OFFSET]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioLeerDirectorio(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));
	memcpy(envio + sizeof(uint64_t) + strlen(arg.path), &(arg.offset), sizeof(off_t));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioBorrarDirectorio(argBorrarDir_t arg){
	return sizeof(uint64_t) + strlen(arg.path);
}

argBorrarDir_t parsearEnvioBorrarDirectorio(char* payload){
	//[LONG_PATH][PATH]

	argBorrarDir_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';

	return arg;
}

char* desparsearEnvioBorrarDirectorio(argBorrarDir_t arg){
	//[LONG_PATH][PATH]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioBorrarDirectorio(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));

	return envio;
}

//------------------------------------------------------------//

uint32_t tamanioEnvioObtenerAtributos(argGetAttr_t arg){
	return sizeof(uint64_t) + strlen(arg.path);
}

argGetAttr_t parsearEnvioObtenerAtributos(char* payload){
	//[LONG_PATH][PATH]

	argGetAttr_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH
	memcpy(&tamanio, payload, 8);
	arg.path = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.path, payload + desplazamiento, tamanio);
	arg.path[tamanio] = '\0';

	return arg;
}

char* desparsearEnvioObtenerAtributos(argGetAttr_t arg){
	//[LONG_PATH][PATH]

	//DESPARSEAMOS
	char* envio = malloc(tamanioEnvioObtenerAtributos(arg));
	uint64_t tamanioPath = strlen(arg.path);
	memcpy(envio, &tamanioPath, sizeof(uint64_t));
	memcpy(envio + sizeof(uint64_t), arg.path, strlen(arg.path));

	return envio;
}

//------------------------------------------------------------//

/*uint32_t tamanioEnvioRenombrar(argRenombrar_t arg){
	return sizeof(uint64_t) + strlen(arg.pathViejo) + sizeof(uint64_t) + strlen(arg.pathNuevo);
}

argRenombrar_t parsearEnvioRenombrar(char* payload){
	//[LONG_PATH][PATH][LONG_PATH][PATH]

	argRenombrar_t arg;
	uint64_t tamanio;
	uint64_t desplazamiento;

	//PARSEAMOS EL PATH VIEJO
	memcpy(&tamanio, payload, 8);
	arg.pathViejo = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(arg.pathViejo, payload + desplazamiento, tamanio);
	arg.pathViejo[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL PATH NUEVO
	memcpy(&tamanio, payload + desplazamiento, 8);
	arg.pathNuevo = (char*) malloc(tamanio + 1);
	desplazamiento += 8;
	memcpy(arg.pathNuevo, payload + desplazamiento, tamanio);
	arg.pathViejo[tamanio] = '\0';

	return arg;
}*/

int32_t parsearReciboSinBuffer(char* payload){
	//[RESULTADO]
	int32_t resultado;
	memcpy(&resultado, payload, 4);
	return resultado;
}

char* desparsearReciboSinBuffer(int32_t resultado){
	char* payload = malloc(sizeof(int32_t));
	memcpy(payload, &resultado, sizeof(int32_t));
	return payload;
}

reciboConBuffer_t parsearReciboConBuffer(char* payload){
	//[LONG_BUFFER][BUFFER][RESULTADO]
	reciboConBuffer_t recibo;
	uint64_t tamanio;
	uint64_t desplazamiento;
	//PARSEAMOS EL BUFFER
	memcpy(&tamanio, payload, 8);
	recibo.tamanio = tamanio;
	recibo.buffer = (char*) malloc(tamanio + 1);
	desplazamiento = 8;
	memcpy(recibo.buffer, payload + desplazamiento, tamanio);
	recibo.buffer[tamanio] = '\0';
	desplazamiento += tamanio;

	//PARSEAMOS EL RESULTADO
	memcpy(&(recibo.resultado), payload + desplazamiento, 4);

	return recibo;
}

uint16_t tamanioReciboConAtributos(int32_t res, mode_t modo, size_t size){
	return (sizeof(int32_t) + sizeof(mode_t) + sizeof(size_t));
}

reciboConAtributos_t parsearReciboConAtributos(char* payload){
	//[RESULTADO][MODO][SIZE]
	reciboConAtributos_t recibo;
	uint64_t desplazamiento = 0;
	memcpy(&(recibo.resultado), payload, 4);
	desplazamiento += 4;
	memcpy(&(recibo.mode), payload + desplazamiento, sizeof(mode_t));
	desplazamiento += sizeof(mode_t);
	memcpy(&(recibo.size), payload + desplazamiento, sizeof(off_t));
	return recibo;
}

char* desparsearReciboConAtributos(int32_t res, mode_t modo, size_t size){
	char* payload = malloc(tamanioReciboConAtributos(res,modo,size));
	memcpy(payload,&res,sizeof(int32_t));
	memcpy(payload+sizeof(int32_t),&modo,sizeof(mode_t));
	memcpy(payload+sizeof(int32_t)+sizeof(mode_t),&size,sizeof(size_t));
	return payload;
}
